Flutter PlatformViewsChannel
在《Flutter Android Virtual Display 实现原理》一文中,完成了对 Virtual displays 模式的 Flutter 侧实现分析。从这一篇开始,进入 Android 侧的实现分析。PlatformViewsChannel是 Flutter SDK 中的一个 Java 类,用于与 Flutter 侧 Virtual displays 模式相关类进行通信。
在 Virtual displays 模式中,Android 原生视图的创建与销毁,完全是由 Flutter 侧 AndroidView 组件的生命周期所驱动。AndroidView 这个 SatefulWidget 控制了什么时候要创建、销毁原生视图。两者之间通过 Channel 进行通信,在 Dart 一头的 Channel 为 SystemChannels.platform_views
(具体参见《Flutter TextureAndroidViewController》,在 Android 一侧对应的接收方就是本文的 PlatformViewsChannel。
不论是 Virtual displays 模式还是 Hybrid composition 模式,他们在 Android 侧对接的都是 PlatformViewsChannel。
核心成员
该类有两个成员值得关注:
// 与 Flutter 通信的 Channel
private final MethodChannel channel;
// 接口类,代理实现
private PlatformViewsHandler handler;
PlatformViewsChannel 中只负责消息的接收、解析,并不包含具体处理逻辑。具体处理逻辑都通过 PlatformViewsHandler 接口进行。而该接口的实现,位于 PlatViewsController 中。
PlatformViewsHandler 接口
PlatformViewsHandler 接口声明了 Virtual displays 模式下,Flutter 侧与 Android 侧通信的所有能力,这些方法如下:
- createAndroidViewForPlatformView:对应 Hybrid composition 模式,创建平台视图
- disposeAndroidViewForPlatformView:对应 Hybrid composition 模式,销毁平台视图
- createVirtualDisplayForPlatformView:对应 Virtual displays 模式,创建平台视图
- disposeVirtualDisplayForPlatformView:对应 Virtual displays 模式,销毁平台视图
- resizePlatformView:调整平台视图大小
- onTouch:由 Flutter 触发向平台视图分发手势
- setDirection:由 Flutter 触发调整布局方向
- clearFocus:清除焦点
- synchronizeToNativeViewHierarchy:设置是否在添加
PlatformView
时,将 FlutterView 的渲染表面转换为Flutter FlutterImageView。FlutterImageView
是 Flutter 在 Android 侧,展示 Flutter 界面时的一种特殊的视图- 默认为 true
其中,对于 synchronizeToNativeViewHierarchy 并没有讲解透彻,这部分留到分析 Hybrid composition 模式时,在进行透彻研究。
PlatformViewCreationRequest 接口
在创建平台视图的 API 中,参数中包含一个 PlatformViewCreationRequest 类型的参数,这是创建平台视图所需的信息:
/** Request sent from Flutter to create a new platform view. */
public static class PlatformViewCreationRequest {
// 视图 ID,由 Flutter 侧创建
public final int viewId;
// 视图类型
@NonNull public final String viewType;
/** The density independent width to display the platform view. */
public final double logicalWidth;
/** The density independent height to display the platform view. */
public final double logicalHeight;
// 布局方向
public final int direction;
// 视图的构建参数
@Nullable public final ByteBuffer params;
}
接收消息
PlatformViewsChannel 并不复杂,本质上是个 Channel,设置 setMethodCallHandler 来接受 Flutter 侧消息。首先在构造函数中关联 Channel:
public PlatformViewsChannel(@NonNull DartExecutor dartExecutor) {
channel =
new MethodChannel(dartExecutor, "flutter/platform_views", StandardMethodCodec.INSTANCE);
channel.setMethodCallHandler(parsingHandler);
}
由 parsingHandler 负责解析:
private final MethodChannel.MethodCallHandler parsingHandler =
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
//...
switch (call.method) {
case "create":
create(call, result);
break;
case "dispose":
dispose(call, result);
break;
case "resize":
resize(call, result);
break;
case "touch":
touch(call, result);
break;
case "setDirection":
setDirection(call, result);
break;
case "clearFocus":
clearFocus(call, result);
break;
case "synchronizeToNativeViewHierarchy":
synchronizeToNativeViewHierarchy(call, result);
break;
default:
result.notImplemented();
}
}
其中:parsingHandler 创建了一个匿名内部类实例,create、dispose 这些方法都定义在内部类内部。
通过上面代码,能清晰了解到 platform_views
这条 Channel 上传递事件的全集。接下来我们对这些方法进行逐个分析。处理逻辑都是一样的:解析参数,调用 PlatformViewsHandler 中对应的 API,下面以 create 方法为例。
MethodCallHandler.create
private void create(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
Map<String, Object> createArgs = call.arguments();
// 是否是 Hybrid composition 模式
boolean usesHybridComposition =
createArgs.containsKey("hybrid") && (boolean) createArgs.get("hybrid");
// Hybrid composition 模式下,尺寸由 the Flow layer 的尺寸决定
double width = (usesHybridComposition) ? 0 : (double) createArgs.get("width");
double height = (usesHybridComposition) ? 0 : (double) createArgs.get("height");
PlatformViewCreationRequest request =
new PlatformViewCreationRequest(
(int) createArgs.get("id"), // 视图 id
(String) createArgs.get("viewType"), // 视图类型
width, // 视图宽度
height, // 视图高度
(int) createArgs.get("direction"), // 视图方向
createArgs.containsKey("params") // 视图创建参数
? ByteBuffer.wrap((byte[]) createArgs.get("params"))
: null);
try {
// 根据不同模式,调用不同的 API
if (usesHybridComposition) {
handler.createAndroidViewForPlatformView(request);
result.success(null);
} else {
// Virtual Display 模式下,创建的原生视图得到一个纹理 id,需要传回给 Flutter 侧
long textureId = handler.createVirtualDisplayForPlatformView(request);
result.success(textureId);
}
} catch (IllegalStateException exception) {
result.error("error", detailedExceptionString(exception), null);
}
}
本文作者:Maeiee
本文链接:Flutter PlatformViewsChannel
版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!
喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!